package com.commons.loadbalancer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author mis_wu
 * @date 2022/4/12 21:44
 * 负载均衡-轮询算法实现
 * 实现原理:假如有两台服务器集群 ( 访问次数 % 2 ) 即 (访问次数 % 集群.size)
 * 调 1 次 % 2 = 1
 * 调 2 次 % 2 = 0
 * 调 2 次 % 2 = 1
 * 调 4 次 % 2 = 0
 * ...
 */
@Component
public class RotationLoadBalancer implements LoadBalancer {

    /**
     * 从0开始计数
     */
    private AtomicInteger atomicInteger = new AtomicInteger(0);

    @Override
    public ServiceInstance getSingleAddres(List<ServiceInstance> serviceInstances) {
        int index = atomicInteger.incrementAndGet() % serviceInstances.size();
        return serviceInstances.get(index);
    }

    /**
     * 负载均衡在项目中的使用方法
     */
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private DiscoveryClient discoveryClient;
    @Autowired
    private LoadBalancer loadBalancer;
    @RequestMapping("/test")
    public Object loadBalancer(){
        //根据服务名在服务注册中心获取集群列表地址
        List<ServiceInstance> instances = discoveryClient.getInstances("cloud-admins");
        //列表任意选一个 实现本地rpc调用,采用负载均衡算法
        ServiceInstance singleAddres = loadBalancer.getSingleAddres(instances);
        //获取服务的url  (ip:port)
        URI uri = singleAddres.getUri();
        //调用其他服务接口(一般在项目中不使用RestTemplate)
        Object obj = restTemplate.getForObject(uri + "/getMovieUsers", Object.class);
        return obj;
    }
}
